﻿using Jint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace 自动校园网登陆
{
    internal class LoginHandler
    {
        private string get_challenge_api = "http://172.16.8.8/cgi-bin/get_challenge";
        private string srun_portal_api = "http://172.16.8.8/cgi-bin/srun_portal";

        private string username, password, ip;

        public LoginHandler(string username, string password)
        {
            this.username = username;
            this.password = password;
            ip = Util.GetIPAddress();
        }

        public string TryLogin()
        {
            string jquery1 = string.Format("jQuery112404953340710317169_{0}", Util.GetTotalSeconds());
            Dictionary<string, string> param = new Dictionary<string, string>
            {
                { "callback",  jquery1},
                { "username", username },
                { "ip", ip },
                { "_", string.Format("{0}", Util.GetTotalSeconds())}
            };
            string responseJson = Util.GetResponseText(get_challenge_api, param);
            if (responseJson == "offline_error")
                return responseJson;
            Regex r = new Regex(jquery1 + "\\({\"challenge\":\"(.*)\",\"client_ip\"");

            string token = r.Match(responseJson).Groups[1].Value;
            string json = "{" + "\"username\":\"" + username + "\",\"password\":\"" + password + "\",\"ip\":\"" + ip + "\",\"acid\":\"1\",\"enc_ver\":\"srun_bx1\"}".Replace(" ", "");
            string hmd5 = Util.HmacMD5(password, token);


            Engine eng = new Engine();
            eng.Execute("function xEncode(str, key) {\r\n\t\tif (str == \"\") {\r\n            return \"\";\r\n        }\r\n        var v = s(str, true),\r\n            k = s(key, false);\r\n        if (k.length < 4) {\r\n            k.length = 4;\r\n        }\r\n        var n = v.length - 1,\r\n            z = v[n],\r\n            y = v[0],\r\n            c = 0x86014019 | 0x183639A0,\r\n            m,\r\n            e,\r\n            p,\r\n            q = Math.floor(6 + 52 / (n + 1)),\r\n            d = 0;\r\n        // console.log(q)\r\n        while (0 < q--) {\r\n            d = d + c & (0x8CE0D9BF | 0x731F2640);\r\n            e = d >>> 2 & 3;\r\n            for (p = 0; p < n; p++) {\r\n                y = v[p + 1];\r\n                m = z >>> 5 ^ y << 2;\r\n                m += (y >>> 3 ^ z << 4) ^ (d ^ y);\r\n                m += k[(p & 3) ^ e] ^ z;\r\n                z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);\r\n            }\r\n            y = v[0];\r\n            m = z >>> 5 ^ y << 2;\r\n            m += (y >>> 3 ^ z << 4) ^ (d ^ y);\r\n            m += k[(p & 3) ^ e] ^ z;\r\n            z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);\r\n        }\r\n        return l(v, false);\r\n\t}\r\n\tfunction s(a, b) {\r\n        var c = a.length, v = [];\r\n        for (var i = 0; i < c; i += 4) {\r\n            v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;\r\n        }\r\n        if (b) {\r\n            v[v.length] = c;\r\n        }\r\n        return v;\r\n    }\r\n    function l(a, b) {\r\n        var d = a.length, c = (d - 1) << 2;\r\n        if (b) {\r\n            var m = a[d - 1];\r\n            if ((m < c - 3) || (m > c))\r\n                return null;\r\n            c = m;\r\n        }\r\n        for (var i = 0; i < d; i++) {\r\n            a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);\r\n        }\r\n        if (b) {\r\n            return a.join('').substring(0, c);\r\n        } else {\r\n            return a.join('');\r\n        }\r\n    }\r\n");
            var s = eng.Invoke("xEncode", json, token).ToObject();

            Engine eng2 = new Engine();
            eng2.Execute("var _PADCHAR = \"=\"\r\n    , _ALPHA = \"LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA\"\r\n    , _VERSION = \"1.0\";\r\nfunction _getbyte64(s, i) {\r\n    var idx = _ALPHA.indexOf(s.charAt(i));\r\n    if (idx === -1) {\r\n        throw \"Cannot decode base64\"\r\n    }\r\n    return idx\r\n}\r\nfunction _setAlpha(s) {\r\n    _ALPHA = s;\r\n}\r\nfunction _getbyte(s, i) {\r\n    var x = s.charCodeAt(i);\r\n    if (x > 255) {\r\n        throw \"INVALID_CHARACTER_ERR: DOM Exception 5\"\r\n    }\r\n    return x\r\n}\r\nfunction _encode(s) {\r\n    if (arguments.length !== 1) {\r\n        throw \"SyntaxError: exactly one argument required\"\r\n    }\r\n    s = String(s);\r\n    var i, b10, x = [], imax = s.length - s.length % 3;\r\n    if (s.length === 0) {\r\n        return s\r\n    }\r\n    for (i = 0; i < imax; i += 3) {\r\n        b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8) | _getbyte(s, i + 2);\r\n        x.push(_ALPHA.charAt(b10 >> 18));\r\n        x.push(_ALPHA.charAt((b10 >> 12) & 63));\r\n        x.push(_ALPHA.charAt((b10 >> 6) & 63));\r\n        x.push(_ALPHA.charAt(b10 & 63))\r\n    }\r\n    switch (s.length - imax) {\r\n        case 1:\r\n            b10 = _getbyte(s, i) << 16;\r\n            x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _PADCHAR + _PADCHAR);\r\n            break;\r\n        case 2:\r\n            b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8);\r\n            x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _ALPHA.charAt((b10 >> 6) & 63) + _PADCHAR);\r\n            break\r\n    }\r\n    return x.join(\"\")\r\n}\r\n");
            var ss = eng2.Invoke("_encode", s).ToObject();
            string i = "{SRBX1}" + ss;

            string chkstr = token + username;
            chkstr += token + hmd5;
            chkstr += token + "1";
            chkstr += token + ip;
            chkstr += token + "200";
            chkstr += token + "1";
            chkstr += token + i;

            string jquery2 = string.Format("jQuery11240645308969735664_{0}", Util.GetTotalSeconds());

            Dictionary<string, string> param2 = new Dictionary<string, string>
            {
                { "callback",  jquery2},
                { "action", "login" },
                { "username", username },
                { "password", "{MD5}" + hmd5 },
                { "ac_id", "1" },
                { "ip", ip },
                { "chksum",  Util.GetSHA1(chkstr)},
                { "info", i },
                { "n", "200" },
                { "type", "1" },
                { "os", "windows+10" },
                { "name", "windows" },
                { "double_stack", "0" },
                { "_", string.Format("{0}", Util.GetTotalSeconds())}
            };

            string srun_portal_response = Util.GetResponseText(srun_portal_api, param2);
            return srun_portal_response;
        }
    }
}
